package com.wenx.v3system.modular.cloud.service.impl;

import com.wenx.permission.context.DataPermissionContextHolder;
import com.wenx.permission.context.PermissionConditionInfo;
import com.wenx.permission.service.PermissionVerificationService;
import com.wenx.v3secure.utils.LoginUser;
import com.wenx.v3system.modular.cloud.domain.po.SysPermissionCondition;
import com.wenx.v3system.modular.cloud.service.SysPermissionConditionRestService;
import com.wenx.v3system.modular.cloud.service.SysDepartmentRestService;
import com.wenx.v3system.modular.cloud.service.SysUserRoleService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 权限验证服务实现
 * 负责权限条件的验证和处理逻辑
 * 支持权限验证与SQL注入分离的架构设计
 * 
 * @author wenx
 * @since 1.0.0
 */
@Slf4j
@Service
public class PermissionVerificationServiceImpl implements PermissionVerificationService {
    
    private final SysPermissionConditionRestService permissionConditionRestService;
    private final SysDepartmentRestService departmentRestService;
    private final SysUserRoleService userRoleService;
    
    /**
     * 占位符匹配模式
     */
    private static final Pattern PLACEHOLDER_PATTERN = Pattern.compile("#\\{([^}]+)\\}");
    
    /**
     * 安全拒绝访问条件
     */
    private static final String DENY_ACCESS_CONDITION = "1 = 0";
    
    /**
     * 数字类型占位符集合
     */
    private static final Set<String> NUMERIC_PLACEHOLDERS = Set.of(
        "userId", "deptId", "departmentId"
    );
    
    /**
     * 构造函数注入，遵循用户偏好
     */
    public PermissionVerificationServiceImpl(SysPermissionConditionRestService permissionConditionRestService,
                                           SysDepartmentRestService departmentRestService,
                                           SysUserRoleService userRoleService) {
        this.permissionConditionRestService = permissionConditionRestService;
        this.departmentRestService = departmentRestService;
        this.userRoleService = userRoleService;
    }
    
    @Override
    public PermissionConditionInfo verifyAndBuildCondition(String tableName, String permissionType, String customCondition) {
        log.debug("开始验证权限条件 - 表名: {}, 权限类型: {}, 自定义条件: {}", tableName, permissionType, customCondition);
        
        // 用户认证检查
        if (!LoginUser.isAuthenticated()) {
            return buildFailedCondition(tableName, "用户未登录");
        }
        
        // 超级管理员跳过权限验证
        if (LoginUser.isSuperAdmin()) {
            return buildSkippedCondition(tableName, "超级管理员跳过权限验证");
        }
        
        PermissionConditionInfo.PermissionConditionInfoBuilder builder = PermissionConditionInfo.builder()
                .tableName(tableName)
                .permissionType(permissionType)
                .status(PermissionConditionInfo.VerificationStatus.PENDING);
        
        try {
            // 权限条件构建优先级：数据库配置 > 自定义条件 > 预定义类型 > 默认拒绝
            return buildPermissionCondition(builder, tableName, permissionType, customCondition);
        } catch (Exception e) {
            log.error("权限验证失败 - 表名: {}, 错误: {}", tableName, e.getMessage(), e);
            return buildFailedCondition(tableName, "权限验证异常: " + e.getMessage());
        }
    }
    
    @Override
    public List<PermissionConditionInfo> verifyAndBuildConditions(String[] tableNames, String permissionType, String customCondition) {
        return Arrays.stream(tableNames)
                .map(tableName -> verifyAndBuildCondition(tableName, permissionType, customCondition))
                .collect(Collectors.toList());
    }
    
    @Override
    public List<PermissionConditionInfo.DatabaseCondition> getDatabaseConditions(String tableName) {
        try {
            List<SysPermissionCondition> conditions = permissionConditionRestService.getByTableName(tableName);
            return conditions.stream()
                    .filter(this::isValidCondition)
                    .map(this::convertToInternalCondition)
                    .collect(Collectors.toList());
        } catch (Exception e) {
            log.warn("获取数据库权限条件失败 - 表名: {}, 错误: {}", tableName, e.getMessage());
            return Collections.emptyList();
        }
    }
    
    @Override
    public String buildFinalSqlCondition(PermissionConditionInfo conditionInfo) {
        return Optional.ofNullable(conditionInfo)
                .filter(info -> info.getStatus() == PermissionConditionInfo.VerificationStatus.VERIFIED)
                .map(PermissionConditionInfo::getFinalCondition)
                .orElse(null);
    }
    
    @Override
    public boolean hasTablePermission(String tableName) {
        PermissionConditionInfo conditionInfo = verifyAndBuildCondition(tableName, null, null);
        return conditionInfo.getStatus() != PermissionConditionInfo.VerificationStatus.FAILED;
    }
    
    // ==================== 私有方法 ====================
    
    /**
     * 构建权限条件的核心逻辑
     */
    private PermissionConditionInfo buildPermissionCondition(PermissionConditionInfo.PermissionConditionInfoBuilder builder,
                                                           String tableName, String permissionType, String customCondition) {
        // 1. 优先处理数据库配置的权限条件
        List<PermissionConditionInfo.DatabaseCondition> databaseConditions = getDatabaseConditions(tableName);
        if (!databaseConditions.isEmpty()) {
            String finalCondition = buildDatabaseCondition(databaseConditions);
            if (StringUtils.hasText(finalCondition)) {
                return builder
                        .finalCondition(finalCondition)
                        .databaseConditions(databaseConditions)
                        .status(PermissionConditionInfo.VerificationStatus.VERIFIED)
                        .build();
            }
        }
        
        // 2. 处理自定义条件
        if (StringUtils.hasText(customCondition)) {
            String finalCondition = buildConditionFromTemplate(customCondition);
            return builder
                    .originalCondition(customCondition)
                    .finalCondition(finalCondition)
                    .status(PermissionConditionInfo.VerificationStatus.VERIFIED)
                    .build();
        }
        
        // 3. 处理预定义权限类型
        if (StringUtils.hasText(permissionType)) {
            String template = DataPermissionContextHolder.getConditionTemplate(permissionType);
            if (StringUtils.hasText(template)) {
                String finalCondition = buildConditionFromTemplate(template);
                return builder
                        .originalCondition(template)
                        .finalCondition(finalCondition)
                        .status(PermissionConditionInfo.VerificationStatus.VERIFIED)
                        .build();
            }
        }
        
        // 4. 默认安全策略 - 拒绝访问
        log.warn("表 {} 没有配置任何权限条件，应用默认安全策略（拒绝访问）", tableName);
        return builder
                .finalCondition(DENY_ACCESS_CONDITION)
                .status(PermissionConditionInfo.VerificationStatus.VERIFIED)
                .errorMessage("未配置权限条件，应用默认安全策略")
                .build();
    }
    
    /**
     * 从模板构建条件 - 安全策略优化版本
     */
    private String buildConditionFromTemplate(String template) {
        if (!StringUtils.hasText(template)) {
            log.warn("没有权限条件模板，应用拒绝访问策略");
            return DENY_ACCESS_CONDITION;
        }
        
        Matcher matcher = PLACEHOLDER_PATTERN.matcher(template);
        StringBuffer result = new StringBuffer();
        
        while (matcher.find()) {
            String placeholder = matcher.group(1);
            String value = getPlaceholderValue(placeholder);
            
            if (value != null) {
                String replacement = formatSqlValue(value, placeholder);
                matcher.appendReplacement(result, Matcher.quoteReplacement(replacement));
            } else {
                log.warn("占位符 {} 无法获取值，应用拒绝访问策略防止全表扫描", placeholder);
                return DENY_ACCESS_CONDITION;
            }
        }
        
        matcher.appendTail(result);
        return result.toString();
    }
    
    /**
     * 构建数据库条件
     */
    private String buildDatabaseCondition(List<PermissionConditionInfo.DatabaseCondition> conditions) {
        List<String> validConditions = conditions.stream()
                .map(this::buildSingleCondition)
                .filter(StringUtils::hasText)
                .collect(Collectors.toList());
        
        return validConditions.isEmpty() ? DENY_ACCESS_CONDITION : String.join(" AND ", validConditions);
    }
    
    /**
     * 构建单个数据库条件
     */
    private String buildSingleCondition(PermissionConditionInfo.DatabaseCondition condition) {
        // 优先使用SQL表达式
        if (StringUtils.hasText(condition.getValue()) && condition.getValue().startsWith("SQL:")) {
            String sqlExpression = condition.getValue().substring(4);
            return buildConditionFromTemplate(sqlExpression);
        }
        
        // 使用字段条件构建
        Object contextValue = getContextValue(condition);
        if (contextValue == null) {
            log.warn("无法获取条件上下文值: {}", condition);
            return DENY_ACCESS_CONDITION;
        }
        
        return buildFieldCondition(condition, contextValue);
    }
    
    /**
     * 构建字段条件
     */
    private String buildFieldCondition(PermissionConditionInfo.DatabaseCondition condition, Object contextValue) {
        String field = condition.getField();
        String operator = condition.getOperator();
        String value = contextValue instanceof String ? 
            "'" + contextValue + "'" : contextValue.toString();
        
        switch (operator) {
            case "=": return field + " = " + value;
            case "!=": return field + " != " + value;
            case ">": return field + " > " + value;
            case "<": return field + " < " + value;
            case ">=": return field + " >= " + value;
            case "<=": return field + " <= " + value;
            case "like": return field + " LIKE '%" + contextValue + "%'";
            case "in": return field + " IN (" + value + ")";
            case "not_in": return field + " NOT IN (" + value + ")";
            default: 
                log.warn("不支持的操作符: {}", operator);
                return DENY_ACCESS_CONDITION;
        }
    }
    
    /**
     * 获取上下文值
     */
    private Object getContextValue(PermissionConditionInfo.DatabaseCondition condition) {
        String contextField = condition.getContextField();
        
        // 没有上下文字段，直接返回值
        if (!StringUtils.hasText(contextField) || !contextField.contains(".")) {
            return condition.getValue();
        }
        
        String[] parts = contextField.split("\\.", 2);
        if (parts.length != 2) {
            return null;
        }
        
        String source = parts[0];
        String field = parts[1];
        
        // 只支持user上下文源
        if (!"user".equals(source)) {
            return null;
        }
        
        return getUserContextValue(field);
    }
    
    /**
     * 获取用户上下文值
     */
    private Object getUserContextValue(String field) {
        switch (field) {
            case "id":
            case "userId": 
                return LoginUser.getUserId();
            case "username": 
                return LoginUser.getUsername();
            case "departmentId": 
                return LoginUser.getDepartmentId();
            default: 
                return null;
        }
    }
    
    /**
     * 获取占位符对应的值 - 完善版本
     */
    private String getPlaceholderValue(String placeholder) {
        if (!LoginUser.isAuthenticated()) {
            return null;
        }
        
        switch (placeholder) {
            case "userId":
                return Optional.ofNullable(LoginUser.getUserId()).map(String::valueOf).orElse(null);
            case "username":
                return LoginUser.getUsername();
            case "deptId":
            case "departmentId":
                return Optional.ofNullable(LoginUser.getDepartmentId()).map(String::valueOf).orElse(null);
            case "deptIds":
                return getDeptAndSubDeptIds();
            case "roleIds":
                return getUserRoleIds();
            default:
                log.debug("未知的占位符: {}", placeholder);
                return null;
        }
    }
    
    /**
     * 获取用户所在部门及其子部门ID列表 - 完善实现
     */
    private String getDeptAndSubDeptIds() {
        Long deptId = LoginUser.getDepartmentId();
        if (deptId == null) {
            return null;
        }
        
        try {
            // 获取当前部门及其所有子部门
            List<Long> deptUsers = departmentRestService.getDepartmentUsers(deptId, true);
            Set<Long> allDeptIds = new HashSet<>();
            allDeptIds.add(deptId); // 包含当前部门
            
            // 如果有用户，说明部门存在，可以继续获取子部门
            if (!deptUsers.isEmpty()) {
                // 这里应该有获取子部门ID的方法，暂时只返回当前部门
                // TODO: 可以通过departmentRestService.getChildDepartments递归获取
            }
            
            return allDeptIds.stream()
                    .map(String::valueOf)
                    .collect(Collectors.joining(","));
        } catch (Exception e) {
            log.warn("获取部门及子部门ID失败，用户ID: {}, 部门ID: {}", LoginUser.getUserId(), deptId, e);
            return deptId.toString(); // 降级处理：只返回当前部门
        }
    }
    
    /**
     * 获取用户角色ID列表
     */
    private String getUserRoleIds() {
        Long userId = LoginUser.getUserId();
        if (userId == null) {
            return null;
        }
        
        try {
            List<Long> roleIds = userRoleService.getRoleIdsByUserId(userId);
            return roleIds.isEmpty() ? null : 
                   roleIds.stream().map(String::valueOf).collect(Collectors.joining(","));
        } catch (Exception e) {
            log.warn("获取用户角色ID失败，用户ID: {}", userId, e);
            return null; // 安全策略：获取失败时返回null，触发拒绝访问
        }
    }
    
    /**
     * 格式化SQL值，确保语法正确
     */
    private String formatSqlValue(String value, String placeholder) {
        // 数字类型的占位符不需要引号
        if (NUMERIC_PLACEHOLDERS.contains(placeholder)) {
            return value;
        }
        
        // 列表类型（如deptIds）不需要额外引号
        if (placeholder.endsWith("Ids") || placeholder.endsWith("ids")) {
            return value;
        }
        
        // 字符串类型需要单引号，并转义已有的单引号
        return "'" + value.replace("'", "''") + "'";
    }
    
    /**
     * 检查条件是否有效
     */
    private boolean isValidCondition(SysPermissionCondition condition) {
        return condition.getStatus() != null && condition.getStatus() == 1;
    }
    
    /**
     * 转换为内部条件格式
     */
    private PermissionConditionInfo.DatabaseCondition convertToInternalCondition(SysPermissionCondition condition) {
        return PermissionConditionInfo.DatabaseCondition.builder()
                .field(condition.getField())
                .operator(condition.getOperator())
                .value(condition.getValue())
                .contextField(condition.getContextField())
                .status(condition.getStatus())
                .type(condition.getType())
                .description(condition.getDescription())
                .build();
    }
    
    /**
     * 构建失败的条件信息
     */
    private PermissionConditionInfo buildFailedCondition(String tableName, String errorMessage) {
        return PermissionConditionInfo.builder()
                .tableName(tableName)
                .status(PermissionConditionInfo.VerificationStatus.FAILED)
                .errorMessage(errorMessage)
                .build();
    }
    
    /**
     * 构建跳过的条件信息
     */
    private PermissionConditionInfo buildSkippedCondition(String tableName, String reason) {
        return PermissionConditionInfo.builder()
                .tableName(tableName)
                .status(PermissionConditionInfo.VerificationStatus.SKIPPED)
                .errorMessage(reason)
                .build();
    }
}